#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import binascii
import struct
import threading
import socket
import datetime
import time
import globalvar as Globalvar
from ctypes import *
from multiprocessing import Queue


def example(express, result=None):
    if result is None:
        result = eval(express)
    # print(express, ' ==> ', result)
    return result


def sentmsg(session, subject, udp_socket, dest_addr, exam_round=1, info=0):
    # 帧标识符
    send_Head = b"RHZT"
    # 源地址id
    send_Source = 14
    # 目的地址id
    send_Dest = 12
    # 信息交换时标
    time_mark = str(datetime.datetime.now())[11:-3]
    time_mark = time_mark.replace(":", "")
    time_mark = time_mark.replace(".", "")
    send_TimeMark = int(time_mark)
    # 报文尾
    send_check = 1
    # 准备发送的数据
    if info == 0:
        # 信息类别码
        send_InfoCode = 42000
        # 信息长度即报文体字节数
        send_length = 1
        # 报文体，0表示未运行，1表示运行中
        send_msg = 1
        send_data = struct.pack('<4sHHHII?B', send_Head, send_Source, send_Dest, send_InfoCode,
                                send_length, send_TimeMark, send_msg, send_check)
    else:
        # 信息类别码
        send_InfoCode = 42002
        # 信息长度即报文体字节数
        send_length = 16
        # 报文体
        send_session = session
        send_subject = subject
        send_exam_round = exam_round
        if info == 1:
            # 提交答案
            send_state = 3
        elif info == 2:
            # 消息已更新
            send_state = 2
        send_data = struct.pack('<4sHHHIIiiiiB', send_Head, send_Source, send_Dest, send_InfoCode,
                                send_length, send_TimeMark, send_session, send_subject, send_exam_round, send_state, send_check)
    udp_socket.sendto(send_data, dest_addr)
    print("********send data to cilent********")


def recvmsg(udp_socket):
    flag = True
    while True:
        # 一次性接受1024字节数据，返回一个元组，其中有数据有地址
        global data, addr
        data, addr = udp_socket.recvfrom(1024)
        # 设置发送ip地址
        Globalvar.set_send_id_addr(addr)
        # print('Received from %s:%s.' % addr)
        if len(data) == 39:
            # 信息码24002为参赛方获取客户端考试状态
            headers = example(r"struct.unpack('<4sHHHII', data[:18])")
            print("字节流：", data, "\n字节大小：", len(data))
            print("报文头：", headers)
            print("报文体：考试科目，考试情景，考试场次编号，考试状态，考试时间")
            content = example(r"struct.unpack('<iiiif', data[18:-1])")
            if content[3] == 0:
                # 开始比赛
                Globalvar.set_msg_content_value(content)
                Globalvar.set_recv_msg_content(True)
                # 记录当前考试场次
                Globalvar.set_exam_round(content[2])
            elif content[3] == 1:
                # 收到动态信息回复已更新
                tempContent = Globalvar.get_msg_content_value()
                sentmsg(tempContent[0], tempContent[1], udp_socket, addr, exam_round=Globalvar.get_exam_round(), info=2)
            print(content)
        elif len(data) == 20:
            # 24000为参赛方获取客户端状态
            # headers = example(r"struct.unpack('<4sHHHII', data[:18])")
            # print("字节流：", data, "\n字节大小：", len(data))
            # print("报文头：", headers)
            # print("报文体：运行状态")
            # content = example(r"struct.unpack('<?', data[18:-1])")
            # print(content)
            if flag:
                sentmsg(1, 1, udp_socket, addr)
                flag = False


if __name__ == "__main__":
    Objdll = cdll.LoadLibrary("./DLLtest.dll")
    # 创建套接字
    s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
    # 绑定端口:
    s.bind(('202.118.13.194', 10014))  # 收
    # 发 10012
    print('Bind UDP on 10014...')
    # 创建线程接收数据
    recv_thread = threading.Thread(target=recvmsg, args=(s,))
    recv_thread.start()

